/*
看门狗，用作阻拦索

*/
#include <stdio.h>
#include <string.h>


typedef struct Link_Id
{
	unsigned int destIp;
	unsigned int sourIp;
	unsigned short destPort;
	unsigned short sourPort;
}LinkId;


typedef struct Packet_Elem
{
	LinkId *lid;
	int pacLen;
	unsigned int packet_id;
	//struct Prision_Elem *prev;
	struct Packet_Elem *next;
	unsigned char *data;

}PacketElem;


typedef struct Queue_Head
{
	PacketElem * head;
	PacketElem * rear;
	int size;

}QueueHead;

//返回0，小端；返回1，大端
int checkBigEndian()
{
	union checkbox
	{
		int i;
		unsigned char carr[4];
	}cbox;

	cbox.i=1;
	if(cbox.carr[3]==0x00)
	{
		return 0;//小端
	}
	else
	{
		return 1;//大端
	}	
}


//获得一封数据包的四元组
//the parameter must points to a ip packets
LinkId * getLinkId(unsigned char *packet)
{
	LinkId *lid;
	lid=(LinkId *)malloc(sizeof(LinkId));
	union Ip
	{
		unsigned int myip;
		unsigned char ipbuf[4];
	}u_IP;
	union Port
	{
		unsigned short myport;
		unsigned char portbuf[2];
	}u_PORT;

	if(checkBigEndian()==0)
	{
		u_IP.ipbuf[0]=*(packet+15);
		u_IP.ipbuf[1]=*(packet+14);
		u_IP.ipbuf[2]=*(packet+13);
		u_IP.ipbuf[3]=*(packet+12);
		
		lid->sourIp=u_IP.myip;
		
		u_IP.ipbuf[0]=*(packet+19);
		u_IP.ipbuf[1]=*(packet+18);
		u_IP.ipbuf[2]=*(packet+17);
		u_IP.ipbuf[3]=*(packet+16);

		lid->destIp=u_IP.myip;

		u_PORT.portbuf[0]=*(packet+21);
		u_PORT.portbuf[1]=*(packet+20);	
		lid->sourPort=u_PORT.myport;
		
		u_PORT.portbuf[0]=*(packet+23);
		u_PORT.portbuf[1]=*(packet+22);	
		lid->destPort=u_PORT.myport;
	}
	else
	{
		//大端的处理暂时没做
	}

//printf("lid:  dip is %u,sip is %u,dpt is %u,spt is %u\n",lid->destIp,lid->sourIp,lid->destPort,lid->sourPort);
	return lid;
}


//返回1说明是结束包；返回0说明不是
int checkEndPack(unsigned char *packet,int pacLen)
{
	if((packet[pacLen-3]==0x2e)&&(packet[pacLen-2]==0x0d)&&(packet[pacLen-1]==0x0a))
		return 1;
	else
		return 0;
}


//封装数据包到拦截链节点
//返回0成功；返回1失败
PacketElem * getPack(unsigned char *packet,LinkId * lid,unsigned int pacId,int pacLen)
{
	PacketElem *pe;
	pe=(PacketElem *)malloc(sizeof(PacketElem));
	
	pe->lid=lid;

	//拷贝数据包的内容	
	pe->data=(unsigned char *)malloc(pacLen);
	if(pe->data==NULL)
	{
		perror("malloc");
		exit(1);
	}
	memcpy(pe->data,packet,pacLen);
	
	pe->pacLen=pacLen;
	pe->packet_id=pacId;
	pe->next=NULL;
	
	return pe;
}

//回收节点
int mem_cleaner(PacketElem * pe)
{
	free(pe->lid);
	free(pe->data);
	free(pe);
}


//初始化拦截队列
QueueHead * init_intercept_queue(void)
{
	QueueHead * temp;
	temp=(QueueHead *)malloc(sizeof(QueueHead));
	if(temp==NULL)
	{
		perror("malloc");
		exit(1);
	}
	
	temp->head=NULL;
	temp->rear=NULL;
	temp->size=0;

	return temp;
}


//入队函数
int enQueue(QueueHead *qh,PacketElem *pe)
{
	if(qh->size==0)
	{
		qh->head=pe;
		qh->rear=pe;
		
		pe->next=NULL;
		//pe->prev=NULL;

		qh->size=1;
	}
	else if(qh->size>0)
	{
		qh->rear->next=pe;
		qh->rear=pe;
		qh->size+=1;
	}

	//printf("after enqueue,size is %d\n",qh->size);
	return 0;
}

//出队函数(暂时没用)
PacketElem * deQueue(QueueHead *qh)
{
	PacketElem * temp;

	if(qh->size==0)
	{
		exit(1);
	}
	else if(qh->size==1)
	{
		temp=qh->head;
		qh->rear=NULL;
		qh->head=NULL;
		qh->size=0;
		return temp;
	}
	else if(qh->size > 1)
	{
		temp=qh->head;
		qh->head=qh->head->next;
		qh->size-=1;
		return temp;
	}	
	
}


//检查一个end包是否在queue中
//如果在，则返回1；如果不在，则返回0
int checkQueue(QueueHead *qh,LinkId *lid)
{
	PacketElem * curtemp;

	if(qh->size==0)
	{
		return 0;
	}
	else
	{
		curtemp=qh->head;
		while(curtemp!=NULL)
		{
			if((curtemp->lid->destIp==lid->destIp)&&(curtemp->lid->sourIp==lid->sourIp)&&\
				(curtemp->lid->destPort==lid->destPort)&&(curtemp->lid->sourPort==lid->sourPort))
			{
						return 1;
			}
			else
			{
				curtemp=curtemp->next;
			}
		}		
		return 0;
		
	}
		
}


//在队列中查找节点，并删除对应元素
PacketElem * delOnePac(QueueHead *qh,LinkId *lid)
{
	PacketElem * curtemp;
	PacketElem * pretemp;

	if(qh->size==0)
	{
		return 0;
	}
	else
	{
		pretemp=qh->head;
		curtemp=pretemp->next;
		
		//如果队首节点即需要删除的节点，那么删之
		if((pretemp->lid->destIp==lid->destIp)&&(pretemp->lid->sourIp==lid->sourIp)&&\
				(pretemp->lid->destPort==lid->destPort)&&(pretemp->lid->sourPort==lid->sourPort))
		{
			qh->size-=1;
			qh->head=qh->head->next;
			return pretemp;						
		}	
	
		while(curtemp!=NULL)
		{
			if((curtemp->lid->destIp==lid->destIp)&&(curtemp->lid->sourIp==lid->sourIp)&&\
				(curtemp->lid->destPort==lid->destPort)&&(curtemp->lid->sourPort==lid->sourPort))
			{
				pretemp->next=curtemp->next;
				qh->size-=1;
				return curtemp;		
			}
			else
			{
				pretemp=curtemp;
				curtemp=curtemp->next;
			}
		}		
		return 0;
		
	}
	
}











